package controllers

import (
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/phpdi/ant-api/devutil/autodoc"
	"gitee.com/phpdi/ant-api/entitys"
	"gitee.com/phpdi/ant-api/services"
	"gitee.com/phpdi/ant-api/utils"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"reflect"
	"strings"
)

type BaseController struct {
	beego.Controller
	authUser       entitys.User //当前已认证用户
	controllerName string       //控制器名称
	actionName     string       //方法名称
	requestType    int          //请求的数据格式

	token string //当前用户token

	autoDoc *autodoc.AutoDoc //自动文档对象



}

// 重写GetString方法，移除前后空格
func (this *BaseController) GetString(name string, def ...string) string {
	return strings.TrimSpace(this.Controller.GetString(name, def...))
}

func (this *BaseController) Prepare() {

	this.controllerName, this.actionName = this.GetControllerAndAction()
	this.controllerName= strings.ToLower(this.controllerName[0 : len(this.controllerName)-10])
	this.actionName = strings.ToLower(this.actionName)

	//默认接受的请求格式
	this.requestType = entitys.RequestTypeFromData

	//token
	this.token=this.Ctx.Input.Header("Token")

	if services.IsDev() {
		this.autoDoc=autodoc.NewAutoDoc("./controllers/")
		logs.Info(
			fmt.Sprintf(
				"IP: %s . Method:%s . URI:%s . Request: %v .RequestBody:%v.",
				this.Ctx.Input.IP(),
				this.Ctx.Request.Method,
				this.Ctx.Request.RequestURI,
				this.Ctx.Input.Context.Request.Form,
				string(this.Ctx.Input.RequestBody),
			),
		)
	}


}



//获取登录用户
func (this *BaseController) getAuthUser()entitys.User {
	if this.authUser.Id> 0 {
		return this.authUser
	}

	if this.token== "" {
		this.checkError(errors.New("token不能为空"))
	}

	auth:=services.NewAuth()
	err:=auth.SetUserByToken(this.token)
	this.checkError(err)


	this.authUser =auth.GetUser()
	return this.authUser
}

//输出json
func (this *BaseController) jsonResult(code uint32, msg string, data interface{}) {
	this.Data["json"] = entitys.JsonResult{
		Code: code,
		Msg:  msg,
		Data: data,
	}

	//自动文档
	if this.autoDoc!= nil {
		if err:=this.autoDoc.SetResponse(data).Make();err!= nil {
			logs.Info("BaseController.jsonResult 错误:",err)
		}
	}

	this.ServeJSON()
	this.StopRun()
}

//错误检查
func (this *BaseController) checkError(err error) {

	if err == nil {
		return
	}

	var (
		code uint32
	)
	code = entitys.CodeErr

	if webErr, ok := err.(entitys.WebErr); ok {
		code = webErr.Code
		//记录带有原始错误的err
		if webErr.OriginalMsg != "" {
			logs.Info("checkError:", webErr.OriginalMsg)
		}

	}
	this.jsonResult(code, err.Error(), nil)
}

//设置请求格式
func (this *BaseController) setRequestType(requestType int) *BaseController {
	this.requestType = requestType
	return this
}



//从application/json中解析出数据，并且验证数据格式
func (this *BaseController) parseFormData(obj interface{}, params ...interface{}) {

	var (
		requiredFiled []string //必填字段
		customTag map[string]string //自定义tag
	)



	//解析参数
	for _,v:=range params {
		switch value:=v.(type) {
		case string:
			requiredFiled=append(requiredFiled,value)
		case map[string]string:
			customTag=value
		}
	}

	v := reflect.ValueOf(obj)
	if v.Kind() != reflect.Ptr {
		this.checkError(errors.New("obj 必须为指针"))
	}

	//自动文档
	if this.autoDoc!=nil {
		this.autoDoc.SetUrl(this.controllerName+"/"+this.actionName).//请求地址
			SetMethod(this.Ctx.Request.Method).//请求方式
			SetRequiredFields(requiredFiled).//必传参数
			SetRequest(obj)//输入参数
	}

	switch this.requestType {
	case entitys.RequestTypeApplicationJson: //application/json
		if len(this.Ctx.Input.RequestBody) == 0 {
			return
		}
		//解析表单数据
		this.checkError(json.Unmarshal(this.Ctx.Input.RequestBody, obj))
	case entitys.RequestTypeFromData: //from-data,x-www-form-urlencoded
		this.checkError(this.Controller.ParseForm(obj))
	default:
		return
	}

	//结构体去空
	utils.TrimStruct(obj)

	//验证表单数据
	valid := utils.NewValidation().Require(requiredFiled...)

	//传入了自定义验证tag
	if len(customTag) > 0 {
		valid.FieldTag(customTag)
	}

	if err := valid.Valid(obj); err != nil {
		this.checkError(entitys.NewWebErr(entitys.CodeValidFail, err.Error()))
	}

}

//必须为post请求
func (this *BaseController) mustPost() {
	if !(this.Ctx.Request.Method == "POST") {
		this.jsonResult(entitys.CodeErr, "非法请求", nil)
	}
}



//渲染模版
func (this *BaseController) display(tpl ...string) {

	var tplname string
	if len(tpl) > 0 {
		tplname = tpl[0] + ".html"
	} else {
		tplname = this.controllerName + "/" + this.actionName + ".html"
	}

	this.Layout = "shared/layout_page.html"
	this.TplName = tplname

	this.LayoutSections = make(map[string]string)
	//this.LayoutSections["Header"] = "layout/sections/header.html"
	//this.LayoutSections["Footer"] = "layout/sections/footer.html"
	//this.LayoutSections["Navbar"] = "layout/sections/navbar.html"
	//this.LayoutSections["Sidebar"] = "layout/sections/sidebar.html"
	//
	//
	//this.Data["auth"] = this.auth
	//this.Data["ctx"] = this.Ctx

}


//检查结果 参数1为输出结果，参数2 为错误
func (this *BaseController) result(params ...interface{}) {
	var (
		res interface{}
		resErr error
	)

	switch len(params) {
	case 0:
		this.jsonResult(entitys.CodeOK, "", nil)
	case 1,2:
		for _,v:=range params {
			if err,ok:=v.(error); ok {
				resErr=err
			}else{
				if res== nil {
					res=v
				}
			}
		}

		this.checkError(resErr)

		this.jsonResult(entitys.CodeOK, "", res)

	default:
		this.jsonResult(entitys.CodeErr, "输出参数错误", nil)

	}

}